All messages
OPENID 2.0 - parameters in POST messages *only* be extracted from the body

openid.ns = "http://specs.openid.net/auth/2.0" (if absent or "http://openid.net/signon/1.[01]", then interpret as 1.1)
openid.mode = if absent, request is not an OpenID message.

Request Parameters
==================
GET
Common:
    openid.mode = "checkid_immediate" or "checkid_setup"
    openid.assoc_handle = (optional) The assoc_handle from the associate request.
    openid.return_to = (optional in 2.0) URL where the Provider SHOULD return the User-Agent back to.

OpenID 1.0/1.1:
    openid.ns = absent or "http://openid.net/signon/1.[01]"
    openid.identity = Claimed Identifier
    openid.trust_root = (optional) URL the OP SHALL ask the End User to trust. (Default: return_to URL) (Optional; 

OpenID 2.0:
    openid.ns = "http://specs.openid.net/auth/2.0"
    openid.claimed_id = (optional) The Claimed Identifier.
    openid.identity = (optional) The OP-Local Identifier.
    openid.realm = Value: (optional) URL pattern the OP SHOULD ask the end user to trust. See Section 9.2. (Default .return_to URL)

    "openid.claimed_id" and "openid.identity" SHALL be either both present or both absent. 
    .realm  MUST be sent if .return_to is omitted.

    If a different OP-Local Identifier is not specified, the claimed identifier MUST be used as the value for openid.identity.
    client may want to pre-sign .return_to if it contains state information


Response Parameters
===================

checkid_immediate failed Response
------------------------------
OpenID 1.0/1.1:
    openid.mode = "id_res"
    openid.user_setup_url = URL to redirect User-Agent to so the End User can do whatever's necessary to fulfill the assertion.

OpenID 2.0 Failed checkid_immediate response
    openid.mode = "setup_needed"


checkid_setup cancelled 
-----------------------
Common:
    openid.mode = "cancel" 

generic error response
----------------------
OpenID 2.0:
    openid.mode = "error"
    openid.error = A human-readable message indicating the cause of the error.
    openid.contact = (optional) Contact address for the administrator of the sever. 
    openid.reference = (optional) A reference token, such as a support ticket number or a URL to a news blog, etc.

positive response
-----------------
Common:
    openid.mode = "id_res"
    openid.assoc_handle = The handle for the association that was used to sign this assertion.
    openid.invalidate_handle = (optional) association handle sent in the request if the Provider did not accept or recognize it. 
    openid.signed = Comma-seperated list of signed fields (without the "openid." prefix) that the signature covers. (e.g., "mode,identity,return_to").
    openid.sig = base64(HMAC(secret(assoc_handle), key-value format string of signed key values)
    openid.return_to = Verbatim copy of the return_to URL parameter sent in the request, before the Provider modified it.

OpenID 1.0/1.1
    openid.identity = Verified Identifier

OpenID 2.0
    openid.op_endpoint = The OP Endpoint URL.
    openid.claimed_id = (optional) The Claimed Identifier. 
    openid.identity = (optional) The OP-Local Identifier
    openid.response_nonce = ...

    .claimed_id and .identity SHALL be either both present or both absent.
    .signed MUST contain at least "op_endpoint", "return_to" "response_nonce" and "assoc_handle", and if present in the response, "claimed_id" and "identity". Additional keys MAY be signed as part of the message. See Generating Signatures.

    .response_nonce is a string 255 characters or less in length, that MUST be unique to this particular successful authentication response. The nonce MUST start with the current time on the server, and MAY contain additional ASCII characters in the range 33-126 inclusive (printable non-whitespace characters), as necessary to make each response unique. 
($y,$m,$d,$h,$m,$s) = m/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})Z/
(all times UTC, no fractional seconds)




